package com.ilop.sthome.mvp.present.config;

import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Handler;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;

import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.util.Log;
import android.view.View;

import com.aliyun.alink.business.devicecenter.api.add.AddDeviceBiz;
import com.aliyun.alink.business.devicecenter.api.add.DeviceInfo;
import com.aliyun.alink.business.devicecenter.api.add.IAddDeviceListener;
import com.aliyun.alink.business.devicecenter.api.add.LinkType;
import com.aliyun.alink.business.devicecenter.api.add.ProvisionStatus;
import com.aliyun.alink.business.devicecenter.base.DCErrorCode;
import com.aliyun.iot.aep.sdk.apiclient.callback.IoTResponse;
import com.example.common.base.OnCallBackToRefresh;
import com.example.common.mvp.BasePresenterImpl;
import com.example.common.mvp.onModelCallBack;
import com.example.common.utils.SpUtil;
import com.ilop.sthome.common.CommonId;
import com.ilop.sthome.common.bind.DeviceBindBusiness;
import com.ilop.sthome.common.bind.OnBindDeviceCompletedListener;
import com.ilop.sthome.common.command.SendDeviceCommand;
import com.ilop.sthome.data.bean.Device;
import com.ilop.sthome.data.enums.DevType;
import com.ilop.sthome.data.greenDao.DeviceInfoBean;
import com.ilop.sthome.mvp.contract.config.ConnectNetContract;
import com.ilop.sthome.mvp.model.CommonModel;
import com.ilop.sthome.mvp.model.common.CommonModelImpl;
import com.ilop.sthome.ui.activity.config.QuestionActivity;
import com.ilop.sthome.ui.activity.config.RecoveryGuideActivity;
import com.ilop.sthome.ui.activity.device.GatewayMainActivity;
import com.ilop.sthome.ui.dialog.BaseDialog;
import com.ilop.sthome.utils.ParsingJsonUtil;
import com.ilop.sthome.utils.greenDao.utils.DeviceDaoUtil;
import com.ilop.sthome.utils.greenDao.utils.SceneDaoUtil;
import com.siterwell.familywellplus.R;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author skygge
 * @date 2020/4/17.
 * GitHub：javofxu@github.com
 * email：skygge@yeah.net
 * description：
 */
public class ConnectNetPresenter extends BasePresenterImpl<ConnectNetContract.IView> implements ConnectNetContract.IPresent{
    private static final String TAG = ConnectNetPresenter.class.getSimpleName();
    private Context mContext;

    private String mRoomId;
    private String mDeviceName;
    private String mProductKey;

    private int mCurrentCount = 0;//当前进度
    private int mCurrentSpeed = 1;//当前速度
    private int SPEED0 = 500;
    private final int SPEED1 = 1000;
    private final int SPEED2 = 5000;
    private final int SPEED3 = 20000;
    private int mStatus = -1; //0代表参数错误,1代表绑定成功,2代表绑定失败,3代表已被其他用户绑定,4代表回调绑定失败,5代表用户重复绑定,6代表获取网关信息
    private String mFailMsg = null;

    private String mWiFiSSId;
    private String mWiFiPwd;
    private boolean isPhoneAp = false;

    private Timer mTimer;
    private Handler mHandler;
    private DeviceBindBusiness mBindBusiness;
    private CommonModelImpl mModel;

    private BaseDialog mDialog;

    public ConnectNetPresenter(Context mContext, Handler handler) {
        this.mContext = mContext;
        mProductKey = DevType.EE_GATEWAY.getProductkey(); // 商家后台注册的 productKey，不可为空
        this.mHandler = handler;
        mModel = new CommonModel(mHandler);
        mRoomId = SpUtil.getString(mContext, CommonId.KEY_BIND_ROOM);
    }

    @Override
    public void getInitialization(String ssId, String pwd, boolean isWiFiAp) {
        this.mWiFiSSId = ssId;
        this.mWiFiPwd = pwd;
        this.isPhoneAp = isWiFiAp;
        mView.showInitializationView();
    }

    @Override
    public void smartOrApConnect(boolean isPhoneAp) {
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.productKey = mProductKey;
        deviceInfo.linkType = isPhoneAp?LinkType.ALI_PHONE_AP.getName():LinkType.ALI_DEFAULT.getName(); // 默认一键配网
        startConfig(deviceInfo);
        SPEED0 = isPhoneAp ? 200 : 500;
    }

    @Override
    public void startConfig(DeviceInfo deviceInfo) {
        AddDeviceBiz.getInstance().setDevice(deviceInfo);//设置待添加设备的基本信息
        AddDeviceBiz.getInstance().startAddDevice(mContext, new IAddDeviceListener() {
            @Override
            public void onPreCheck(boolean isSuccess, DCErrorCode dcErrorCode) {
                // 参数检测回调 当 DeviceInfo 校验完成后触发
                Log.i(TAG, "startConfig: 参数检测" + isSuccess);
                if (isSuccess){
                    startConnectNet();
                }else {
                    parameterError();
                }
            }

            @Override
            public void onProvisionPrepare(int prepareType) {
                Log.i(TAG, "startConfig: 配网类型" + prepareType);
                // 手机热点配网、设备热点配网、一键配网、蓝牙辅助配网、二维码配网会走到该流程，
                // 零配和智能路由器配网不会走到该流程。
                // prepareType = 1提示用户输入账号密码
                // prepareType = 2提示用户手动开启指定热点 aha 12345678
                // 执行完上述操作之后，调用toggleProvision接口继续执行配网流程
                if (prepareType == 1) {
                    AddDeviceBiz.getInstance().toggleProvision(mWiFiSSId, mWiFiPwd, 60);
                }
            }

            @Override
            public void onProvisioning() {
                // TODO 当开始配网时触发
                Log.i(TAG, "startConfig: 开始配网");
                if (isPhoneAp){
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        mView.showConnectMessage(mContext.getString(R.string.to_change_wifi_before_and_turn_back));
                    }else {
                        mView.showConnectMessage(mContext.getString(R.string.esptouch_is_configuring));
                    }
                    checkWiFiStatus();
                }
            }

            @Override
            public void onProvisionStatus(ProvisionStatus provisionStatus) {
                // 二维码配网会走到这里  provisionStatus=ProvisionStatus.QR_PROVISION_READY表示二维码ready了
                // ProvisionStatus.QR_PROVISION_READY.message() 获取二维码内容
                // 注意：返回二维码时已开启监听设备是否已配网成功的通告，并开始计时，UI端应提示用户尽快扫码；
                // 如果在指定时间配网超时了，重新调用开始配网流程并刷新二维码；
            }

            @Override
            public void onProvisionedResult(boolean isConnected, DeviceInfo deviceInfo, DCErrorCode dcErrorCode) {
                // 配网结果 如果配网成功之后包含token，请使用配网成功带的token做绑定
                Log.i(TAG, "startConfig: 配网结果" + isConnected);
                if(isConnected){
                    connectNetSuccess(deviceInfo);
                }else {
                    mStatus = 2;
                    mFailMsg = "Error code:" + dcErrorCode.code + " \t\tmessage:" + dcErrorCode.msg;
                }
            }
        });
    }

    @Override
    public void startConnectNet() {
        mTimer = new Timer();
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                mCurrentCount = mCurrentCount + mCurrentSpeed;
                mHandler.post(()-> refreshProgress(mCurrentCount));
                switch (mStatus) {
                    case -1:
                        mCurrentSpeed = SPEED0;
                        break;
                    case 1:
                        mCurrentSpeed = SPEED1;
                        break;
                    case 5:
                    case 6:
                        mCurrentSpeed = SPEED2;
                        break;
                    default:
                        mCurrentSpeed = SPEED3;
                        break;
                }
            }
        };
        mTimer.schedule(timerTask, 0,100);
    }

    @Override
    public void refreshProgress(int progress) {
        float number = progress/2000f;
        if (number >= 100f){
            mView.showCurrentProgress("100%");
            if (mTimer != null){
                mTimer.cancel();
                mTimer = null;
            }
            if(mStatus == 6){
                mView.bindSuccess(mDeviceName);
            } else if (mStatus == 5){
                mView.showAlreadyInRoom(mDeviceName);
            } else {
                connectNetError();
            }
        }else {
            String current = Math.round(number) + "%";
            mView.showCurrentProgress(current);
        }
    }

    @Override
    public void connectNetSuccess(DeviceInfo deviceInfo) {
        if (deviceInfo != null) {
            mView.showConnectNetSuccess(deviceInfo.deviceName);
            this.mDeviceName = deviceInfo.deviceName;
            Device device = new Device();
            device.pk = deviceInfo.productKey;
            device.dn = deviceInfo.deviceName;
            mBindBusiness = new DeviceBindBusiness();
            mBindBusiness.queryProductInfo(device);
            DeviceInfoBean mDevice = DeviceDaoUtil.getInstance().findGatewayByDeviceName(deviceInfo.deviceName);
            if (mDevice == null){
                bindDevice(device);
            }else {
                mStatus = 5;
            }
        }else {
            parameterError();
        }
    }

    @Override
    public void bindDevice(Device device) {
        mBindBusiness.bindDevice(device, new OnBindDeviceCompletedListener() {
            @Override
            public void onSuccess(String iotId) {
                mStatus = 1;
                setCurrentGateway(iotId);
            }

            @Override
            public void onFailed(Exception e) {
                mStatus = 4;
                mFailMsg =  mContext.getString(R.string.EE_AS_SYS_BINDING_PHONE_CODE6);
            }

            @Override
            public void onFailed(int code, String message, String localizedMsg) {
                mStatus = code == 2064 ? 3 : 4;
                mFailMsg = localizedMsg;
            }
        });
    }

    @Override
    public void connectNetError() {
        mCurrentCount = 0;
        mView.showConnectNetError(mStatus, mFailMsg);
    }

    @Override
    public void parameterError() {
        if (mTimer != null){
            mTimer.cancel();
            mTimer = null;
        }
        mCurrentCount = 0;
        mView.showConnectNetError(0, mContext.getString(R.string.EE_PARAM_ERROR));
    }

    @Override
    public void removeProductInfo() {
        if (mTimer != null){
            mTimer.cancel();
            mTimer = null;
        }
        if (mHandler!=null){
            mHandler.removeCallbacksAndMessages(null);
        }
    }

    @Override
    public void checkWiFiStatus() {
        WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager!=null) {
            if (wifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLED) { //wifi关闭状态
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ //Android 10.0
                    Intent panelIntent = new Intent(Settings.Panel.ACTION_WIFI);
                    mView.startForResultByIntent(panelIntent);
                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){//android 7.0以上
                    onSkipToOpenWiFi();
                } //android 7.0以下不用进行任何操作 等待配网完成
            }
        }
    }

    @Override
    public void onSkipToOpenWiFi() {
        if (mDialog == null || !mDialog.isShowing()){
            mDialog = new BaseDialog(mContext, new OnCallBackToRefresh() {
                @Override
                public void onConfirm() {
                    Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
                    mView.startActivityByIntent(intent);
                }

                @Override
                public void onCancel() {
                }
            });
            mDialog.setTitleAndButton(mContext.getString(R.string.to_change_wifi_before_and_turn_back),
                    mContext.getString(R.string.cancel), mContext.getString(R.string.goto_set));
            mDialog.show();
        }
    }

    @Override
    public void skipToGateway(String deviceName) {
        Intent intent = new Intent(mContext, GatewayMainActivity.class);
        intent.putExtra(CommonId.KEY_ADD_NEW, true);
        intent.putExtra(CommonId.KEY_DEVICE_NAME, deviceName);
        mHandler.postDelayed(()-> mView.startActivityByIntent(intent), 1000);
    }

    @Override
    public void setCurrentGateway(String iotId) {
        String mGatewayName = SpUtil.getString(mContext, CommonId.KEY_GATEWAY);
        if (TextUtils.isEmpty(mGatewayName)){
            getGatewayList();
        }else {
            renameGateway(iotId, mGatewayName);
        }
    }

    @Override
    public void renameGateway(String iotId, String nickname) {
        mModel.onRenameGateway(iotId, nickname, new onModelCallBack() {
            @Override
            public void onResponse(IoTResponse response) {
                if (response.getCode() == 200){
                    getGatewayList();
                }else {
                    mHandler.post(() -> mView.showToastMsg(response.getLocalizedMsg()));
                }
            }
            @Override
            public void onFailure(Exception e) {
            }
        });
    }

    @Override
    public void getGatewayList() {
        mModel.onGetGatewayList(new onModelCallBack() {
            @Override
            public void onResponse(IoTResponse response) {
                if (response.getCode() == 200){
                    getCurrentGateway(response.getData());
                }else {
                    mHandler.post(()->mView.showToastMsg(response.getLocalizedMsg()));
                }
            }

            @Override
            public void onFailure(Exception e) {

            }
        });
    }

    @Override
    public void setGatewayRoomId(DeviceInfoBean gateway) {
        SendDeviceCommand mSend = new SendDeviceCommand(mContext, gateway);
        mSend.queryOrSetGatewayInfo("01", mRoomId);
        mStatus = 6;
    }

    private void getCurrentGateway(Object data){
        List<DeviceInfoBean> deviceList = ParsingJsonUtil.getInstance().getGatewayList(data);
        if (deviceList!=null && deviceList.size() > 0) {
            for (DeviceInfoBean deviceInfoBean : deviceList) {
                String deviceName = deviceInfoBean.getDeviceName();
                if (mDeviceName.equals(deviceName)){
                    DeviceDaoUtil.getInstance().insertGateway(deviceInfoBean, mRoomId);
                    SceneDaoUtil.getInstance().addDefaultScene(mContext, deviceName);
                    setGatewayRoomId(deviceInfoBean);
                    break;
                }
            }
        } else {
            DeviceDaoUtil.getInstance().deleteAllGateway();
        }
    }

    @Override
    public SpannableString getReasonSpan() {
        View.OnClickListener l = v -> mView.startActivityByIntent(new Intent(mContext, QuestionActivity.class));
        SpannableString info = new SpannableString(mContext.getString(R.string.config_fail_reason) + "?");
        int end = info.length();
        info.setSpan(new Clickable(l), 0, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return info;
    }

    @Override
    public SpannableString getRestoreFactory() {
        View.OnClickListener l = v -> mView.startActivityByIntent(new Intent(mContext, RecoveryGuideActivity.class));
        SpannableString info = new SpannableString(mContext.getString(R.string.initialzation_guidance_mention2) + "?");
        int end = info.length();
        info.setSpan(new Clickable(l), 0, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return info;
    }

    /**
     * 内部类，用于截获点击富文本后的事件
     */
    class Clickable extends ClickableSpan implements View.OnClickListener {
        private final View.OnClickListener mListener;

        Clickable(View.OnClickListener mListener) {
            this.mListener = mListener;
        }

        @Override
        public void onClick(@NonNull View v) {
            mListener.onClick(v);
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            ds.setColor(ContextCompat.getColor(mContext, R.color.text_title));
            ds.setUnderlineText(true); //超链接的下划线
        }
    }

}
